<template>
  <div class="page-container">
    <el-container>
      <el-header :height="btnList.length === 0 ? '0px' : '45px'" class="operation-header">
        <operation-btn :btn-list="btnList" @handleClickBtn="handleClickBtn" />
      </el-header>
      <el-main class="page-main">
        <el-table
          ref="simpleTable"
          v-loading="tableLoading"
          stripe
          :data="tableData"
          :tree-props="tableTreeProp"
          highlight-current-row
          border
          row-key="menuId"
          :expand-row-keys="expandRowKeys"
          :height="btnList.length === 0 ? 'calc(100vh - 99px)' : 'calc(100vh - 140px)'"
          @row-click="rowClick"
        >
          <el-table-column prop="menuName" label="菜单名称" min-width="30%" :formatter="menuNameFormat">
            <template slot="header">
              <span style="display:inline-block;cursor:pointer;width:100%" title="点击展开或收缩列表" @click="expandChange">
                <i style="cursor:pointer;" class="el-icon-arrow-right" />
                <span style="cursor:pointer;">菜单名称</span>
              </span>
            </template>
          </el-table-column>
          <el-table-column prop="isbutton" label="按钮" width="75" align="center" :formatter="buttonFormat" />
          <el-table-column prop="url" label="请求路径" min-width="30%" align="center" />
          <el-table-column prop="componentName" label="组件名称" min-width="25%" align="center" />
          <el-table-column prop="iconcls" label="图标" width="75" align="center"><template slot-scope="scope"><el-tooltip effect="light" :content="scope.row.iconcls" placement="top"><i :class="scope.row.iconcls" class="table-icon" /></el-tooltip></template></el-table-column>
        </el-table>
      </el-main>
    </el-container>
    <!-- 新增、修改对话框 -->
    <el-dialog
      :visible="addDlgVisible"
      :title="addDlgTitle"
      :close-on-click-modal="false"
      width="410px"
      class="add-menu-dialog"
      @close="cancel('addForm')"
    >
      <el-form ref="addForm" :model="addForm" :rules="formRule" class="add-form">
        <el-form-item prop="isMenuRoot">
          <span class="add-form-span">是否根菜单：</span>
          <el-radio-group v-model="addForm.isMenuRoot" @change="$forceUpdate()">
            <el-radio :label="0">否</el-radio>
            <el-radio :label="1">是</el-radio>
          </el-radio-group>
        </el-form-item>
        <el-form-item prop="isbutton">
          <span class="add-form-span">是否按钮：</span>
          <el-radio-group v-model="addForm.isbutton" :disabled="addForm.isMenuRoot===1" @change="$forceUpdate()">
            <el-radio :label="0">否</el-radio>
            <el-radio :label="1">是</el-radio>
          </el-radio-group>
        </el-form-item>
        <el-form-item v-if="addForm.isMenuRoot===0" prop="parentId">
          <span class="add-form-span">父级菜单：</span>
          <el-cascader
            ref="parentSelector"
            v-model="addForm.parentId"
            class="add-form-input"
            clearable
            :show-all-levels="false"
            :options="parentMenuList"
            :props="parentTreeProp"
            @change="parentIdChange"
          />
        </el-form-item>
        <el-form-item prop="menuName">
          <span class="add-form-span">菜单名称：</span>
          <el-input v-model="addForm.menuName" maxlength="30" show-word-limit class="add-form-input" placeholder="输入菜单名称" />
        </el-form-item>
        <el-form-item prop="iconcls">
          <span class="add-form-span">图标：</span>
          <el-input v-model="addForm.iconcls" :title="addForm.iconcls" maxlength="100" :prefix-icon="addForm.iconcls" show-word-limit class="add-form-input" placeholder="输入图标，如el-icon-plus" clearable />
        </el-form-item>
        <el-form-item prop="url">
          <span class="add-form-span">接口路径：</span>
          <el-input v-model="addForm.url" maxlength="100" show-word-limit class="add-form-input" placeholder="接口路径需以/开头" />
        </el-form-item>
        <el-form-item prop="componentName">
          <span class="add-form-span">组件名称：</span>
          <el-input v-model="addForm.componentName" maxlength="100" show-word-limit class="add-form-input" placeholder="输入组件名称" />
        </el-form-item>
      </el-form>
      <div slot="footer">
        <el-button @click="cancel('addForm')">取消</el-button>
        <el-button plain type="primary" :disabled="addBtnDisable" @click="addMenu">确定</el-button>
      </div>
    </el-dialog>
    <!-- 操作记录 -->
    <OperationDlg :show.sync="recordDlg" :record-table="recordTable" />
  </div>
</template>

<script>
import { OperationBtn, OperationDlg } from '@/components/index'
import API from '@/utils/api/baseData/menuManage'
import common from '@/common/common'
import publicAPI from '@/utils/api/public/public'

export default {
  components: { OperationBtn, OperationDlg },
  // name: 'menu',
  data() {
    return {
      tableData: [],
      tableTreeProp: {
        children: 'childMenuInfoTreeSet',
        hasChildren: 'childMenuInfoTreeSet.length!==0'
      },
      tableLoading: true,
      tableRadio: [],
      addDlgVisible: false,
      addDlgTitle: '新增',
      addForm: {
        isMenuRoot: 0,
        isbutton: 0,
        parentId: [],
        menuName: '',
        iconcls: '',
        url: '',
        parent: '',
        componentName: ''
      },
      formRule: {
        isMenuRoot: [{ required: true, message: '*请选择是否根菜单' }],
        isbutton: [{ required: true, message: '*请选择是否菜单' }],
        parentId: [{ required: true, message: '*请选择父级菜单' }],
        menuName: [{ required: true, message: '*请输入菜单名称' }, { validator: common.validateForm().specialWord, trigger: ['blur', 'change'] }],
        iconcls: [{ required: true, message: '*请添加图标' }, { validator: common.validateForm().icon, trigger: ['blur', 'change'] }],
        url: [
          { required: true, message: '*请输入接口路径' },
          { validator: common.validateForm().menuUrl, trigger: ['blur', 'change'] },
          { validator: common.validateForm().Chinese, trigger: ['blur', 'change'] }
        ]
      },
      parentTreeProp: {
        value: 'menuId',
        label: 'menuName',
        children: 'childMenuInfoTreeSet',
        checkStrictly: true
      },
      recordDlg: false,
      recordTable: [],
      addBtnDisable: false,
      expandRowKeys: [],
      rows: []
    }
  },
  computed: {
    parentMenuList() {
      const parentList = common.deepCopy(this.tableData)
      parentList.forEach(menu1 => {
        menu1.childMenuInfoTreeSet.forEach(menu2 => {
          menu2.childMenuInfoTreeSet.forEach(menu3 => {
            menu3.childMenuInfoTreeSet = null
          })
        })
      })
      return parentList
    },
    btnList() {
      return common.getBtn(this.$route.path)
    }
  },
  watch: {
    tableRadio(val) {
      console.log(val)
      const row = val && val.length !== 0 ? val : null
      this.$nextTick(() => {
        this.$refs.simpleTable.setCurrentRow(row)
      })
    }
  },
  created() {
    this.getTableData()
    this.defaultAddForm = common.deepCopy(this.addForm)
  },
  methods: {
    // 操作按钮点击事件
    handleClickBtn: function(val) {
      const data = {
        add: this.addDlg,
        update: this.addDlg,
        moveUp: this.orderMove,
        moveDown: this.orderMove,
        delete: this.dropMenu,
        operationRecord: this.operationRecord
      }
      if (data.hasOwnProperty(val)) {
        data[val] && data[val](val)
      } else {
        this.$warnMsg('未配置此功能')
      }
    },
    // 递归遍历数组
    getAllItem: function(arr, type = 'rows') {
      function fn(arr) {
        let arr1 = []
        for (let i = 0; i < arr.length; i++) {
          if (arr[i].childMenuInfoTreeSet.length !== 0) {
            arr1.push(type === 'rows' ? arr[i] : arr[i].menuId)
            arr1 = arr1.concat(fn(arr[i].childMenuInfoTreeSet, type))
          } else {
            arr1.push(type === 'rows' ? arr[i] : arr[i].menuId)
          }
        }
        return arr1
      }
      return fn(arr, type)
    },
    // 获取表格数据
    getTableData: function() {
      this.tableLoading = true
      API.menuTableAPI().then(response => {
        const res = response.data.data
        if (response.data.flag === 'success') {
          this.tableData = res
          this.expandRowKeys = this.getAllItem(res, 'id')
          this.rows = this.getAllItem(res)
          this.rows.forEach(row => {
            if (row.menuId === this.tableRadio.menuId) {
              this.tableRadio = row
              return
            }
          })
        } else {
          this.$errorMsg(res)
        }
        this.tableLoading = false
      }).catch(error => {
        this.$errorMsg('' + error)
        this.tableLoading = false
      })
    },
    // 按钮名称格式化显示
    menuNameFormat: function(row) {
      const split = row.menuName.split('_')
      if (split.length > 1) {
        return split[1]
      } else {
        return split[0]
      }
    },
    // 是否按钮格式化显示
    buttonFormat: function(row) {
      if (row.isbutton === 1) {
        return '是'
      } else {
        return ''
      }
    },
    // 表格行点击事件
    rowClick: function(row) {
      if (this.tableRadio === row) {
        this.tableRadio = []
      } else {
        this.tableRadio = row
      }
    },
    parentIdChange: function(data) {
      this.addForm.parent = data[data.length - 1]
    },
    // 打开新增、修改对话框
    addDlg: function(val) {
      this.addBtnDisable = false
      if (val === 'add') {
        this.addDlgTitle = '新增'
        this.addDlgVisible = true
      } else {
        const row = this.tableRadio
        if (row.length === 0) {
          this.$warnMsg('请选择要修改的菜单')
        } else {
          this.addDlgTitle = '修改'
          this.addForm = Object.assign({}, row)
          const { parentId } = row
          this.addForm.parent = parentId
          this.addForm.isMenuRoot = parentId === 'menuRoot' ? 1 : 0
          this.addForm.parentId = parentId
          this.addDlgVisible = true
        }
      }
    },
    // 新增、修改对话框确定按钮
    addMenu: function() {
      this.$refs.addForm.validate(valid => {
        if (valid) {
          this.addBtnDisable = true
          const { addForm, addDlgTitle, tableRadio: row } = this
          const { parent, isMenuRoot, isbutton, menuName, iconcls, url, componentName } = addForm
          const parentId = parent && parent !== '' ? parent : 'menuRoot'
          if (addDlgTitle === '新增') {
            const params = {
              _csrf: sessionStorage._csrf,
              isMenuRoot,
              isbutton,
              parentId,
              menuName,
              iconcls,
              url,
              componentName
            }
            API.addMenuAPI(params).then(response => {
              const res = response.data.data
              if (response.data.flag === 'success') {
                this.$successMsg('新增菜单成功')
                this.getTableData()
                this.cancel('addForm')
              } else {
                this.$errorMsg(res)
                this.addBtnDisable = false
              }
            }).catch(error => {
              this.$errorMsg('' + error)
              this.addBtnDisable = false
            })
          } else {
            const params = {
              _csrf: sessionStorage._csrf,
              isMenuRoot,
              isbutton,
              parentId,
              menuName,
              iconcls,
              url,
              componentName,
              menuId: row.menuId
            }
            API.updateAPI(row.menuId, params).then(response => {
              const res = response.data.data
              if (response.data.flag === 'success') {
                this.$successMsg('修改菜单成功')
                this.cancel('addForm')
                this.getTableData()
              } else {
                this.$errorMsg(res)
                this.addBtnDisable = false
              }
            }).catch(error => {
              this.$errorMsg('' + error)
              this.addBtnDisable = false
            })
          }
        }
      })
    },
    // 清空表单
    cancel: function(form) {
      this.addForm = common.deepCopy(this.defaultAddForm)
      this.$nextTick(() => {
        this.$refs[form].clearValidate()
      })
      this.addDlgVisible = false
    },
    // 上移、下移
    orderMove: function(val) {
      const row = this.tableRadio
      const label = val === 'moveUp' ? '上移' : '下移'
      if (row.length === 0) {
        this.$warnMsg('请选择要' + label + '的菜单')
      } else {
        const menuId = row.menuId
        const params = {
          menuId,
          _csrf: sessionStorage._csrf
        }
        API.moveAPI(val, menuId, params).then(response => {
          const res = response.data.data
          if (response.data.flag === 'success') {
            this.$successMsg(label + '成功')
            this.getTableData()
          } else {
            this.$errorMsg(res)
          }
        }).catch(error => { this.$errorMsg('' + error) })
      }
    },
    // 删除菜单
    dropMenu: function() {
      const row = this.tableRadio
      if (row.length === 0) {
        this.$warnMsg('请选择要删除的菜单')
      } else {
        const menuId = row.menuId
        this.$confirm('此操作不可恢复，确定要删除菜单"' + row.menuName + '"吗？', '提示', {
          confirmButtonText: '确定',
          cancelButtonText: '取消',
          type: 'warning'
        }).then(() => {
          const params = {
            menuId,
            _csrf: sessionStorage._csrf
          }
          API.dropMenuAPI(menuId, params).then(response => {
            const res = response.data.data
            if (response.data.flag === 'success') {
              this.$successMsg('删除菜单"' + row.menuName + '"成功')
              this.getTableData()
              this.tableRadio = []
            } else {
              this.$errorMsg(res)
            }
          }).catch(error => { this.$errorMsg('' + error) })
        }).catch(() => { this.$message.info('已取消') })
      }
    },
    // 操作记录
    operationRecord: function() {
      const row = this.tableRadio
      if (row === null || row.length === 0) {
        this.$warnMsg('请选择要查看操作记录的数据')
      } else {
        this.recordDlg = true
        publicAPI.operationDataAPI({ dataId: row.menuId }).then(response => {
          this.recordTable = response.data.content
        }).catch(error => { this.$errorMsg(error) })
      }
    },
    expandChange: function() {
      this.$forceUpdate()
      let expandRowKeys = this.expandRowKeys
      const rows = this.rows
      if (expandRowKeys.length === 0) {
        rows.forEach(row => {
          this.$refs.simpleTable.toggleRowExpansion(row, true)
          expandRowKeys.push(row.menuId)
        })
      } else {
        expandRowKeys = []
        rows.forEach(row => { this.$refs.simpleTable.toggleRowExpansion(row, false) })
      }
      this.expandRowKeys = expandRowKeys
    }
  }
}
</script>

<style lang="scss" scoped>
.operation-header {
  line-height: 45px;
  border-bottom: 1px solid rgb(193, 222, 250);
  min-width: 460px;
}
.page-main {
  height: 100%;
  padding: 5px;
  overflow: hidden;
}
.table-icon {
  font-size: 20px;
}
.add-form-span {
  display: inline-block;
  width: 110px;
  padding-left: 10px;
}
.add-form-input {
  width: 200px;
}
</style>
<style lang="scss">
.add-menu-dialog {
  .el-dialog__body {
    padding: 3px 20px;
  }
  .add-form {
    .el-form-item__error {
      margin-left: 110px;
    }
  }
}
</style>
